﻿using TripLOA.WebService.Serializable;
using TripLOA.WebService.Wrappers;
using System.Collections.Generic;

namespace TripLOA.WebService
{
    /// <summary>
    /// This class defines web-methods for message operations.
    /// </summary>

    public class MessageCore : WsCore
    {

        #region Instance

        /// <summary>
        /// Parameterless Constructor
        /// </summary>
        private MessageCore() { }

        private static MessageCore _instance;


        /// <summary>
        /// Static Constructor.
        /// </summary>
        /// <returns>A new instance of MessageCore</returns>
        public static MessageCore Instance()
        {
            if (_instance == null)
            {
                _instance = new MessageCore();
            }

            return _instance;
        }

        #endregion;

        #region Message Methods

        /// <summary>
        /// Send a message to a list of receivers
        /// </summary>
        /// <param name="authToken">The authentication token</param>
        /// <param name="message">The message to send</param>
        /// <param name="receivers">The list of receivers</param>
        /// <returns>true on success, fail otherwise</returns>
        public WSBool SendMessage(string authToken, Message message, List<string> receivers)
        {
            WSBool wsb = new WSBool();

            if (!UserCore.Instance.checkAuth(authToken, wsb)) return wsb;

            Groupware.Message gm = new Groupware.Message()
            {
                Title = message.Title,
                Text = message.Text,
                Priority = message.Priority
            };

            Groupware.SendReport result = gm.Send(UserCore.Instance.GetLoggedUser(), receivers);

            if (result == null)
            {
                wsb.Status = "fail";
                wsb.Message = "Message is incomplete";
                return wsb;
            }

            wsb.Status = "ok";
            wsb.Payload = true;
            if (!result.Succeded)
            {
                System.Text.StringBuilder notFoundReceivers = new System.Text.StringBuilder();
                System.Text.StringBuilder haveBannedSender = new System.Text.StringBuilder();
                foreach (string rec in result.NonexistentRecipients)
                {
                    notFoundReceivers.Append(" " + rec + ",");
                }
                foreach (string rec in result.HaveBannedSender)
                {
                    haveBannedSender.Append(" " + rec + ",");
                }
                notFoundReceivers.Remove(notFoundReceivers.Length - 2, 2);
                haveBannedSender.Remove(haveBannedSender.Length - 2, 2);
                System.Text.StringBuilder msg = new System.Text.StringBuilder();
                if (result.NonexistentRecipients.Count > 0)
                    msg.Append("Could not find the following receivers:" + notFoundReceivers.ToString());
                if (result.HaveBannedSender.Count > 0)
                    msg.Append("These users have banned you:" + haveBannedSender.ToString());
                wsb.Message = msg.ToString();
            }
            else
            {
                wsb.Message = "Message has been sent to all receivers";
            }
            
            return wsb;
        }

        /// <summary>
        /// Delete message by id
        /// </summary>
        /// <param name="authToken">The authentication token</param>
        /// <param name="messageId">The id of the message to delete</param>
        /// <returns></returns>
        public WSBool DeleteMessage(string authToken, int messageId)
        {
            WSBool wsb = new WSBool();

            if (!UserCore.Instance.checkAuth(authToken, wsb)) return wsb;

            try
            {
                //try to remove received message
                try
                {
                    Groupware.MessageManager.DeleteReceivedMessageById(messageId, UserCore.Instance.GetLoggedUser());
                }
                catch (Storage.Exceptions.MessageNotFoundException)
                {
                    //ignore
                }
                //try to remove sent message
                try
                {
                    Groupware.MessageManager.DeleteSentMessageById(messageId, UserCore.Instance.GetLoggedUser());
                }
                catch (Storage.Exceptions.MessageNotFoundException)
                {
                    //ignore
                }
                wsb.Status = "ok";
                wsb.Payload = true;
                wsb.Message = "Message Deleted";
            }
            catch (System.Exception e)
            {
                wsb.Status = "fail";
                wsb.Message = "Delete Message Failed :" + e.Message;
            }


            return wsb;

        }

        /// <summary>
        /// Get a list of sent messages
        /// </summary>
        /// <param name="authToken">The authentication token</param>
        /// <param name="start">Start index</param>
        /// <param name="max">Max number of messages</param>
        /// <returns>A list of messages</returns>
        public WSMessage GetSentMessages(string authToken, int start, int max)
        {
            WSMessage wsm = new WSMessage();

            if (!UserCore.Instance.checkAuth(authToken, wsm)) return wsm;

            try
            {
                List<Groupware.Message> list = Groupware.MessageManager.RetrieveUserSentMessages(UserCore.Instance.GetLoggedUser(), start, start + max);
                foreach (var m in list)
                {
                    wsm.Payload.Add(new Message(m));
                }
            }
            catch (System.Exception e)
            {
                wsm.Status = "fail";
                wsm.Message = "Impossible to fetch sent messages : " + e.Message;
            }

            return wsm;

        }

        /// <summary>
        /// Mark a message as read
        /// </summary>
        /// <param name="authToken">The authentication token</param>
        /// <param name="messageId">The id of message to mark as read</param>
        /// <returns>true on success, fail otherwise</returns>
        public WSBool MarkMessageAsRead(string authToken, int messageId)
        {
            WSBool wsb = new WSBool();
            if (!UserCore.Instance.checkAuth(authToken, wsb)) return wsb;

            Security.TripLoaUser user = UserCore.Instance.GetLoggedUser();
            Groupware.Message m = Groupware.MessageManager.GetReceivedMessageById(user, messageId);

            try
            {
                m.MarkAsRead(user);
            }
            catch (System.Exception)
            {
                wsb.Status = "fail";
                wsb.Payload = false;
                wsb.Message = "Could not mark message as read";
                return wsb;
            }

            wsb.Status = "ok";
            wsb.Payload = true;
            return wsb;
        }

        /// <summary>
        /// Get a list of received messages
        /// </summary>
        /// <param name="authToken">The authentication token</param>
        /// <param name="start">Start index</param>
        /// <param name="max">Max number of messages</param>
        /// <returns>A list of messages</returns>
        public WSMessage GetReceivedMessages(string authToken, int start, int max)
        {
            WSMessage wsm = new WSMessage();

            if (!UserCore.Instance.checkAuth(authToken, wsm)) return wsm;

            var msgList = Groupware.MessageManager.RetrieveUserReceivedMessages(UserCore.Instance.GetLoggedUser(), start, start + max);

            wsm.Status = "ok";
            foreach (var msg in msgList)
            {
                wsm.Payload.Add(new Message(msg));
            }

            return wsm;
        }

        /// <summary>
        /// Get the list of all unread messages
        /// </summary>
        /// <param name="authToken">The authentication token</param>
        /// <returns>The list of messages</returns>
        public WSMessage GetUnreadMessages(string authToken)
        {
            WSMessage wsm = new WSMessage();
            if (!UserCore.Instance.checkAuth(authToken, wsm)) return wsm;
            List<Groupware.Message> msgList = Groupware.MessageManager.RetrieveUserReceivedMessages(UserCore.Instance.GetLoggedUser());
            foreach (Groupware.Message msg in msgList)
            {
                if (!msg.IsRead)
                    wsm.Payload.Add(new Message(msg));
            }
            return wsm;
        }

        #endregion
    }
}
